package edu.udo.sopra10.chaturaji.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.filechooser.FileNameExtensionFilter;

import edu.udo.sopra10.chaturaji.controllers.GameController;
import edu.udo.sopra10.chaturaji.controllers.SystemController;
import edu.udo.sopra10.chaturaji.exceptions.BadStateException;

public class GameFrame extends JFrame implements ActionListener
{
	private static final long serialVersionUID = -1082841671106613624L;
	
	/* main menu bar */
	private JPanel mainPanel;
	private JMenuBar mainMenuBar;
	private JMenu fileMenu;
	private JMenu helpMenu;
	
	private JTextField currentMoveTextField;
	private JButton gotoLastMoveButton;
	private JButton gotoNextMoveButton;
	private JButton showTipButton;
	private JButton passTurnButton;
	
	private GamePanel gamePanel;
	private OverlayPanel overlay;
	private LogFrame logFrame;
	
	/**
	 * This is the default constructor
	 */
	public GameFrame ()
	{
		super( "Chaturaji" );
		this.setSize( 800, 500 );
		
		initializeMenu();
		initializeInterface();
		
		// add action listeners
		GameController.addBoardResetEventListener( gamePanel );
		GameController.addMoveEventListener( gamePanel );
		GameController.addTurnRequestEventListener( gamePanel );
		GameController.addMoveRequestEventListener( gamePanel );
		GameController.addGameOverEventListener( gamePanel );
		
		// log frame
		logFrame = new LogFrame();
		logFrame.setDefaultCloseOperation( JFrame.HIDE_ON_CLOSE );
		GameController.addBoardResetEventListener( logFrame );
		GameController.addMoveEventListener( logFrame );
		GameController.addPassEventListener( logFrame );
	}
	
	private void initializeMenu ()
	{
		// file menu
		fileMenu = new JMenu( "Spiel" );
		fileMenu.setMnemonic( 's' );
		fileMenu.add( createMenuItem( "Neues Spiel", KeyEvent.VK_N, "newGameMenu", KeyStroke.getKeyStroke( "F2" ) ) );
		fileMenu.add( createMenuItem( "Spiel laden", KeyEvent.VK_L, "loadGameMenu", KeyStroke.getKeyStroke( "F3" ) ) );
		fileMenu
				.add( createMenuItem( "Spiel speichern", KeyEvent.VK_S, "saveGameMenu", KeyStroke.getKeyStroke( "F4" ) ) );
		fileMenu.addSeparator();
		fileMenu.add( createMenuItem( "Logbuch anzeigen", KeyEvent.VK_B, "logMenu", null ) );
		fileMenu.add( createMenuItem( "Highscore anzeigen", KeyEvent.VK_H, "highscoreMenu", null ) );
		fileMenu.add( createMenuItem( "Spielwiederholung laden", KeyEvent.VK_W, "loadReplayMenu", null ) );
		fileMenu.addSeparator();
		fileMenu.add( createMenuItem( "Beenden", KeyEvent.VK_E, "exitMenu", null ) );
		
		// help menu
		helpMenu = new JMenu( "Hilfe" );
		helpMenu.setMnemonic( 'h' );
		helpMenu.add( createMenuItem( "Über…", KeyStroke.getKeyStroke( 'ü' ).getKeyCode(), "aboutMenu", null ) );
		
		// menu bar
		mainMenuBar = new JMenuBar();
		mainMenuBar.add( fileMenu );
		mainMenuBar.add( helpMenu );
		
		this.setJMenuBar( mainMenuBar );
	}
	
	/**
	 * Initializes the interface.
	 * 
	 */
	private void initializeInterface ()
	{
		gotoLastMoveButton = createButton( "«", "gotoLastMoveButton" );
		gotoNextMoveButton = createButton( "»", "gotoNextMoveButton" );
		passTurnButton = createButton( "Passen", "passTurnButton" );
		showTipButton = createButton( "Tipp anzeigen", "showTipButton" );
		
		currentMoveTextField = new JTextField( "" );
		currentMoveTextField.setPreferredSize( new Dimension( 50, -1 ) );
		currentMoveTextField.setMaximumSize( new Dimension( 50, 50 ) );
		currentMoveTextField.setEditable( false );
		
		JToolBar toolBar = new JToolBar( JToolBar.HORIZONTAL );
		toolBar.setBorderPainted( true );
		toolBar.setFloatable( false );
		toolBar.add( new JLabel( "Aktueller Zug:" ) );
		toolBar.addSeparator();
		toolBar.add( gotoLastMoveButton );
		toolBar.add( currentMoveTextField );
		toolBar.add( gotoNextMoveButton );
		toolBar.add( Box.createHorizontalGlue() );
		toolBar.add( passTurnButton );
		toolBar.add( Box.createHorizontalGlue() );
		toolBar.add( showTipButton );
		
		/* overlay */
		overlay = new OverlayPanel();
		this.setGlassPane( overlay );
		
		/* main panel */
		gamePanel = new GamePanel( this );
		
		mainPanel = new JPanel( new BorderLayout() );
		mainPanel.add( gamePanel, BorderLayout.CENTER );
		mainPanel.add( toolBar, BorderLayout.PAGE_END );
		this.setContentPane( mainPanel );
	}
	
	/**
	 * Sets the value of the current turn.
	 * 
	 * @param turnNumber current turn number.
	 * @param player current player.
	 */
	public void setCurrentTurn ( int turnNumber, int player )
	{
		currentMoveTextField.setText( String.valueOf( turnNumber + 1 ) + " / " + String.valueOf( player + 1 ) );
	}
	
	@Override
	public void actionPerformed ( ActionEvent event )
	{
		String action = event.getActionCommand();
		
		if ( action.equals( "passTurnButton" ) )
		{
			gamePanel.passTurn();
		}
		else if ( action.equals( "gotoLastMoveButton" ) )
		{
			try
			{
				GameController.undo();
			}
			catch ( BadStateException e )
			{}
		}
		else if ( action.equals( "gotoNextMoveButton" ) )
		{
			try
			{
				GameController.undo();
			}
			catch ( BadStateException e )
			{}
		}
		else if ( action.equals( "showTipButton" ) )
		{
			gamePanel.showHint();
		}
		else if ( action.equals( "newGameMenu" ) )
		{
			NewGameDialog newGameDialog = new NewGameDialog( this );
			newGameDialog.setDefaultCloseOperation( JDialog.DISPOSE_ON_CLOSE );
			newGameDialog.setVisible( true );
		}
		else if ( action.equals( "loadGameMenu" ) )
		{
			JFileChooser fileChooser = new JFileChooser();
			fileChooser.setFileFilter( new FileNameExtensionFilter( "Chaturaji-Spielstand", "csg" ) );
			fileChooser.setMultiSelectionEnabled( false );
			fileChooser.setAcceptAllFileFilterUsed( false );
			
			if ( fileChooser.showOpenDialog( this ) == JFileChooser.APPROVE_OPTION )
			{
				try
				{
					SystemController.loadGame( fileChooser.getSelectedFile() );
					JOptionPane.showMessageDialog( this, "Das Spiel wurde geladen.", "Erfolgreich",
							JOptionPane.INFORMATION_MESSAGE );
				}
				catch ( IOException e )
				{
					JOptionPane.showMessageDialog( this, "as Spiel konnte nicht geladen werden.", "Fehler",
							JOptionPane.ERROR_MESSAGE );
				}
			}
		}
		else if ( action.equals( "saveGameMenu" ) )
		{
			JFileChooser fileChooser = new JFileChooser();
			fileChooser.setFileFilter( new FileNameExtensionFilter( "Chaturaji-Spielstand", "csg" ) );
			fileChooser.setMultiSelectionEnabled( false );
			fileChooser.setAcceptAllFileFilterUsed( false );
			
			if ( fileChooser.showSaveDialog( this ) == JFileChooser.APPROVE_OPTION )
			{
				try
				{
					SystemController.saveGame( fileChooser.getSelectedFile() );
					JOptionPane.showMessageDialog( this, "Das Spiel wurde gespeichert.", "Erfolgreich",
							JOptionPane.INFORMATION_MESSAGE );
				}
				catch ( IOException e )
				{
					JOptionPane.showMessageDialog( this, "Das Spiel konnte nicht gespeichert werden.", "Fehler",
							JOptionPane.ERROR_MESSAGE );
				}
			}
		}
		else if ( action.equals( "logMenu" ) )
		{
			logFrame.setVisible( true );
		}
		else if ( action.equals( "highscoreMenu" ) )
		{
			HighscoreFrame highscoreFrame = new HighscoreFrame();
			highscoreFrame.setDefaultCloseOperation( JDialog.DISPOSE_ON_CLOSE );
			highscoreFrame.setVisible( true );
		}
		else if ( action.equals( "loadReplayMenu" ) )
		{	

		}
		else if ( action.equals( "exitMenu" ) )
		{
			this.dispose();
		}
		else if ( action.equals( "aboutMenu" ) )
		{
			InformationFrame informationFrame = new InformationFrame();
			informationFrame.setDefaultCloseOperation( JDialog.DISPOSE_ON_CLOSE );
			informationFrame.setVisible( true );
		}
	}
	
	/**
	 * Creates a JMenuItem using the given data.
	 * 
	 * @param label the label of the menu item.
	 * @param mnemonic the mnemonic of the menu item.
	 * @param name the internal name and action command.
	 * @param accelerator the key accelerator or <code>null</code>.
	 * @return the created JMenuItem.
	 */
	private JMenuItem createMenuItem ( String label, int mnemonic, String name, KeyStroke accelerator )
	{
		JMenuItem item = new JMenuItem( label, mnemonic );
		item.setActionCommand( name );
		item.setName( name );
		item.addActionListener( this );
		
		if ( accelerator != null )
			item.setAccelerator( accelerator );
		
		return item;
	}
	
	/**
	 * Creates a JButton using the given data.
	 * 
	 * @param label the label of the menu item.
	 * @param name the internal name and action command.
	 * @return the created JMenuItem.
	 */
	private JButton createButton ( String label, String name )
	{
		JButton button = new JButton( label );
		button.setActionCommand( name );
		button.setName( name );
		button.addActionListener( this );
		
		return button;
	}
}
